<!-- 代码已包含 CSS：使用 TailwindCSS , 安装 TailwindCSS 后方可看到布局样式效果 -->
<template>
  <div
    class="min-h-screen bg-gradient-to-br from-gray-900 to-gray-800 p-8 overflow-hidden"
    :class="{ hide: !showCards, show: showCards }"
  >
    <h1 class="text-4xl font-bold text-center text-white mb-12">
      学生风采展示
    </h1>
    <div
      class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8"
    >
      <div
        v-for="(student, index) in showList"
        :key="student.id"
        class="student-card"
        :style="`--delay: ${index * 0.1}s`"
        @click="toggleCard(student.id)"
        @mouseenter="hoverCard(student.id)"
        @mouseleave="leaveCard(student.id)"
      >
        <div class="card-content">
          <div class="avatar-container">
            <img :src="student.avatar" :alt="student.name" class="avatar" />
          </div>
          <h2 class="name"></h2>
          <p class="class-info">{{ student.class }}</p>
          <div class="tags">
            <span v-for="tag in student.tags" :key="tag" class="tag">
              {{ tag }}
            </span>
          </div>
          <div v-if="expandedCard === student.id" class="additional-info">
            <p>GPA: {{ student.gpa }}</p>
            <p>特长: {{ student.specialty }}</p>
            <p>获奖: {{ student.awards }}</p>
          </div>
        </div>
      </div>
    </div>
    <div class="mt-12 text-center">
      <button
        @click="prevPage"
        class="!rounded-button whitespace-nowrap px-6 py-3 bg-gray-600 hover:bg-gray-700 text-white font-medium transition-all"
      >
        <i class="fas fa-chevron-left mr-2"></i>上一页
      </button>
      <button
        @click="toggleAnimation"
        class="!rounded-button whitespace-nowrap px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium transition-all"
      >
        {{ showCards ? "隐藏学生卡片" : "显示学生卡片" }}
      </button>
      <button
        @click="nextPage"
        class="!rounded-button whitespace-nowrap px-6 py-3 bg-gray-600 hover:bg-gray-700 text-white font-medium transition-all"
      >
        下一页<i class="fas fa-chevron-right ml-2"></i>
      </button>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from "vue";
interface Student {
  id: number;
  name: string;
  class: string;
  avatar: string;
  tags: string[];
  gpa: string;
  specialty: string;
  awards: string;
}
const showCards = ref(true);
const expandedCard = ref<number | null>(null);
const hoveredCard = ref<number | null>(null);
const currentPage = ref(1);
const totalPages = computed(() => Math.ceil(students.value.length / 8));
const showList: any = ref([]);
const students = ref<Student[]>([]);
//伪造更多数据
for (let i = 0; i <= 20; i++) {
  students.value.push({
    id: i,
    name: "吴子豪" + i,
    class: "高二 (4) 班",
    avatar:
      "https://ai-public.mastergo.com/ai/img_res/f52c13120953cdd6fdde3bfed2c7468f.jpg",
    tags: ["计算机社", "数学竞赛", "机器人社"],
    gpa: "3.8",
    specialty: "人工智能",
    awards: "全国青少年信息学奥林匹克竞赛金牌",
  });
}
let timer: any = null;
const prevPage = () => {
  if (currentPage.value > 1) {
    showCards.value = false;
    currentPage.value--;
    timer = setTimeout(() => {
      const start = (currentPage.value - 1) * 8;
      const end = start + 8;
      showList.value = students.value.slice(start, end);
      showCards.value = true;
    }, 1000);
  }
};
const nextPage = () => {
  if (currentPage.value < totalPages.value) {
    showCards.value = false;
    currentPage.value++;
    timer = setTimeout(() => {
      const start = (currentPage.value - 1) * 8;
      const end = start + 8;
      showList.value = students.value.slice(start, end);
      showCards.value = true;
    }, 800);
  }
};
const toggleAnimation = () => {
  showCards.value = !showCards.value;
};
const toggleCard = (id: number) => {
  expandedCard.value = expandedCard.value === id ? null : id;
};
const hoverCard = (id: number) => {
  hoveredCard.value = id;
};
const leaveCard = (id: number) => {
  hoveredCard.value = null;
};
onMounted(() => {
  // 预加载图片
  students.value.forEach((student) => {
    const img = new Image();
    img.src = student.avatar;
  });
  const start = (currentPage.value - 1) * 8;
  const end = start + 8;
  showList.value = students.value.slice(start, end);
});
</script>
<style scoped>
.student-card {
  --card-bg: rgba(255, 255, 255, 0.1);
  --card-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  --card-border: 1px solid rgba(255, 255, 255, 0.1);
  perspective: 1000px;
  transform-style: preserve-3d;
  opacity: 0;
  transform: translateY(100px) scale(0.8);
  will-change: transform, opacity;
}
.show .student-card {
  animation: cardEnter 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  animation-delay: var(--delay);
}
.hide .student-card {
  animation: cardExit 0.6s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards;
}
.student-card:hover .card-content {
  transform: translateY(-10px) scale(1.02);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.card-content {
  background: var(--card-bg);
  backdrop-filter: blur(10px);
  border-radius: 16px;
  padding: 24px;
  border: var(--card-border);
  box-shadow: var(--card-shadow);
  transition: all 0.3s ease;
  cursor: pointer;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.avatar-container {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  overflow: hidden;
  margin-bottom: 16px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.name {
  font-size: 1.5rem;
  font-weight: 600;
  color: white;
  margin-bottom: 8px;
  text-align: center;
}
.class-info {
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 16px;
  font-size: 0.9rem;
}
.tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-bottom: 16px;
}
.tag {
  background: rgba(100, 149, 237, 0.2);
  color: cornflowerblue;
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 0.8rem;
  border: 1px solid rgba(100, 149, 237, 0.3);
}
.additional-info {
  width: 100%;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.9rem;
}
.additional-info p {
  margin-bottom: 8px;
}
@keyframes cardEnter {
  0% {
    opacity: 0;
    transform: translateY(100px) scale(0.8);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
@keyframes cardExit {
  0% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateY(100px) scale(0.8);
  }
}
</style>
